class CartDrawer extends HTMLElement {
  constructor() {
    super();
    this.addEventListener('keyup', (evt) => evt.code === 'Escape' && this.close());
    this.querySelector('#CartDrawer-Overlay').addEventListener('click', this.close.bind(this));
    this.setHeaderCartIconAccessibility();
    
    this.drawerRecommendataion = document.querySelector('drawer-recommendations');
  }

  setHeaderCartIconAccessibility() {
    const cartLink = document.querySelector('#cart-icon-bubble');
    cartLink.setAttribute('role', 'button');
    cartLink.setAttribute('aria-haspopup', 'dialog');
    cartLink.addEventListener('click', (event) => {
      event.preventDefault();
      this.open(cartLink)
    });
    cartLink.addEventListener('keydown', (event) => {
      if (event.code.toUpperCase() === 'SPACE') {
        event.preventDefault();
        this.open(cartLink);
      }
    });
  }

  open(triggeredBy) {
    if (triggeredBy) this.setActiveElement(triggeredBy);
    const cartDrawerNote = this.querySelector('[id^="Details-"] summary');
    if (cartDrawerNote && !cartDrawerNote.hasAttribute('role')) this.setSummaryAccessibility(cartDrawerNote);
    // here the animation doesn't seem to always get triggered. A timeout seem to help
    setTimeout(() => {this.classList.add('animate', 'active')});

    this.addEventListener('transitionend', () => {
      const containerToTrapFocusOn = this.classList.contains('is-empty') ? this.querySelector('.drawer__inner-empty') : document.getElementById('CartDrawer');
      const focusElement = this.querySelector('.drawer__inner') || this.querySelector('.drawer__close');
      trapFocus(containerToTrapFocusOn, focusElement);
    }, { once: true });

    document.body.classList.add('overflow-hidden');
  }

  close() {
    this.classList.remove('active');
    removeTrapFocus(this.activeElement);
    document.body.classList.remove('overflow-hidden');
  }

  setSummaryAccessibility(cartDrawerNote) {
    cartDrawerNote.setAttribute('role', 'button');
    cartDrawerNote.setAttribute('aria-expanded', 'false');

    if(cartDrawerNote.nextElementSibling.getAttribute('id')) {
      cartDrawerNote.setAttribute('aria-controls', cartDrawerNote.nextElementSibling.id);
    }

    cartDrawerNote.addEventListener('click', (event) => {
      event.currentTarget.setAttribute('aria-expanded', !event.currentTarget.closest('details').hasAttribute('open'));
    });

    cartDrawerNote.parentElement.addEventListener('keyup', onKeyUpEscape);
  }

  renderContents(parsedState) {
    this.querySelector('.drawer__inner').classList.contains('is-empty') && this.querySelector('.drawer__inner').classList.remove('is-empty');
    this.productId = parsedState.id;
    this.getSectionsToRender().forEach((section => {
      const sectionElement = section.selector ? document.querySelector(section.selector) : document.getElementById(section.id);
      sectionElement.innerHTML =
          this.getSectionInnerHTML(parsedState.sections[section.id], section.selector);
    }));
    
    if (!this.drawerRecommendataion) {
      this.drawerRecommendataion = document.querySelector('drawer-recommendations');
    }
    this.drawerRecommendataion.execute();

    setTimeout(() => {
      this.querySelector('#CartDrawer-Overlay').addEventListener('click', this.close.bind(this));
      this.open();
    });
  }

  getSectionInnerHTML(html, selector = '.shopify-section') {
    return new DOMParser()
      .parseFromString(html, 'text/html')
      .querySelector(selector).innerHTML;
  }

  getSectionsToRender() {
    return [
      {
        id: 'cart-drawer',
        selector: '#CartDrawer'
      },
      {
        id: 'cart-icon-bubble'
      }
    ];
  }

  getSectionDOM(html, selector = '.shopify-section') {
    return new DOMParser()
      .parseFromString(html, 'text/html')
      .querySelector(selector);
  }

  setActiveElement(element) {
    this.activeElement = element;
  }
}

customElements.define('cart-drawer', CartDrawer);

class CartDrawerItems extends CartItems {
  constructor () {
    super();
    $("#CartDrawer-Checkout").on('click', function () {
      this.querySelector('.loading-overlay__spinner').classList.remove('hidden');
    })
  }
  getSectionsToRender() {
    return [
      {
        id: 'CartDrawer',
        section: 'cart-drawer',
        selector: '.drawer__inner'
      },
      {
        id: 'cart-icon-bubble',
        section: 'cart-icon-bubble',
        selector: '.shopify-section'
      }
    ];
  }
  
  afterRender (state) {
    this.drawerRecommendataion = document.querySelector('drawer-recommendations');
    this.drawerRecommendataion.renderRecommendations(state);
  }
}

customElements.define('cart-drawer-items', CartDrawerItems);

class DrawerRecommendations extends HTMLElement {
  constructor() {
    super();
  }
  
  execute () {
    fetch('/cart.json', fetchConfig('json'))
    .then((response) => response.json())
    .then((state) => {
      this.renderRecommendations(state)
    })
  }
  
  async renderRecommendations(state) {
    const cartDrawerRecommendation = document.querySelectorAll(`#drawer-recommendations-container .loading-overlay`);
    [...cartDrawerRecommendation].forEach((overlay) => {
      overlay.classList.remove('hidden')
    });
    const { items } = state;
    if (items.length === 0) {
      return;
    }
    const cartItemArr = items.reduce((acc, { product_id }) => {
      acc.push({
        product_id
      });
      return acc;
    }, [])
    
    this.callRecommendations(cartItemArr);
  }
  
  async queryRecommendations (url) {
    const res = await fetch(url);
    return res.text();
  }
  
  async callRecommendations (cartItemArr) {
    const urlPrefix = "/recommendations/products?section_id=recommendation-item&limit=4&intent=complementary&product_id=";
    const stack = [];
    for (let i = 0; i < cartItemArr.length; i++ ) {
      const item = cartItemArr[i];
      const text = await this.queryRecommendations(`${urlPrefix}${item.product_id}`);
      const html = document.createElement('div');
      html.innerHTML = text;
      const recommendations = html.querySelectorAll('.cart-recommendations li.grid__item');
      if (typeof recommendations !== 'undefined' && recommendations !== null) {
        for (let k = 0; k < recommendations.length; k++) {
          const id = recommendations[k].id;
          if (!stack[id]) {
            stack[id] = recommendations[k];
          }
        }
      }
    }
    this.render(stack);
  }
  
  render (stack) {
    const nodeContainer = document.querySelector('#drawer-recommendations-container ul');
    Object.keys(stack).forEach((key) => {
      nodeContainer.appendChild(stack[key]);
    })
    
    if (!nodeContainer.hasChildNodes()) {
      const recommendationsTitle = document.querySelector('.drawer-cart-recommendation__heading');
      recommendationsTitle.classList.add('hidden');
    }
    document.querySelectorAll('.recommendation-loading.loading-overlay').forEach((overlay) => overlay.classList.add('hidden'));
  }
}

customElements.define('drawer-recommendations', DrawerRecommendations);
